luci-mod-dashboard: ES6 conversion
authorPaul Donald <[email protected]>
Sun, 29 Jun 2025 20:52:51 +0000 (22:52 +0200)
committerPaul Donald <[email protected]>
Sun, 29 Jun 2025 20:52:51 +0000 (22:52 +0200)
Augment the DNS entries into a table

Closes #7596

Signed-off-by: Paul Donald <[email protected]>
modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css
modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js
modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js
modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js
modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js

index 594a90bb69c36a5b5dbbf91273c4b4a659ba3285..f007c85638f90592cfee3d7f9a2e81add17cd837 100644 (file)
        border-bottom: 1px solid var(--border-color-medium, rgba(0, 0, 0, 0.1));
 }
 
+.Dashboard .table {
+       width: auto;
+       text-align: left;
+}
+
 [data-darkmode="true"] {
        /* invert black SVG line drawings in dark mode */
-       .Dashboard .svgmonotone {
+       .Dashboard
+       .svgmonotone {
                filter: invert(.5);
        }
 }
index 639d372e1e0865a331f900c4272aa2ad70d61c7d..d97fc9cadf93cc6eb9ff2f64d7ff95fffa340a80 100644 (file)
@@ -18,7 +18,7 @@ return baseclass.extend({
 
        params: [],
 
-       load: function() {
+       load() {
                return Promise.all([
                        network.getWANNetworks(),
                        network.getWAN6Networks(),
@@ -27,13 +27,40 @@ return baseclass.extend({
                ]);
        },
 
-       renderHtml: function(data, type) {
+       renderRow(title, value, className = '', tag = 'p') {
+               return E(tag, { 'class': 'mt-2' }, [
+                       E('span', {}, [ title + ':' ]),
+                       E('span', { 'class': className }, [ value ])
+               ]);
+       },
+
+       renderArrayAsTable(title, values) {
+               const table = E('table', { 'class': 'table' });
+
+               if (Array.isArray(values) && values.length > 0) {
+                       values.forEach((val) => {
+                               table.appendChild(E('tr', {}, [
+                                       E('td', {}, [ title + ':' ]),
+                                       E('td', {}, [ val ])
+                               ]));
+                       });
+               } else {
+                       table.appendChild(E('tr', {}, [
+                               E('td', {}, [ title + ':' ]),
+                               E('td', {}, [ '-' ])
+                       ]));
+               }
+
+               return table;
+       },
+
+       renderHtml(data, type) {
 
-               var icon = type;
-               var title = 'router' == type ? _('System') : _('Internet');
-               var container_wapper = E('div', { 'class': type + '-status-self dashboard-bg box-s1'});
-               var container_box = E('div', { 'class': type + '-status-info'});
-               var container_item = E('div', { 'class': 'settings-info'});
+               let icon = type;
+               const title = 'router' == type ? _('System') : _('Internet');
+               const container_wapper = E('div', { 'class': type + '-status-self dashboard-bg box-s1'});
+               const container_box = E('div', { 'class': type + '-status-info'});
+               const container_item = E('div', { 'class': 'settings-info'});
 
                if ('internet' == type) {
                        icon = (data.v4.connected.value || data.v6.connected.value) ? type : 'not-internet';
@@ -52,15 +79,14 @@ return baseclass.extend({
                container_box.appendChild(E('hr'));
 
                if ('internet' == type) {
-                       var container_internet_v4 = E('div');
-                       var container_internet_v6 = E('div');
+                       const container_internet_v4 = E('div');
+                       const container_internet_v6 = E('div');
 
-                       for(var idx in data) {
+                       for(let idx in data) {
 
-                               for(var ver in data[idx]) {
-                                       var classname = ver,
-                                               suppelements = '',
-                                               visible = data[idx][ver].visible;
+                               for(let ver in data[idx]) {
+                                       let classname = ver;
+                                       const visible = data[idx][ver].visible;
 
                                        if('connected' === ver) {
                                                classname = data[idx][ver].value ? 'label label-success' : 'label label-danger';
@@ -79,22 +105,20 @@ return baseclass.extend({
                                                }
 
                                                if ('addrsv4' === ver) {
-                                                       var addrs = data[idx][ver].value;
+                                                       const addrs = data[idx][ver].value;
                                                        if(Array.isArray(addrs) && addrs.length) {
-                                                               for(var ip in addrs) {
+                                                               for(let ip in addrs) {
                                                                        data[idx][ver].value = addrs[ip].split('/')[0];
                                                                }
                                                        }
                                                }
 
                                                if (visible) {
-                                                       container_internet_v4.appendChild(
-                                                               E('p', { 'class': 'mt-2'}, [
-                                                                       E('span', {'class': ''}, [ data[idx][ver].title + ':' ]),
-                                                                       E('span', {'class': classname }, [ data[idx][ver].value ]),
-                                                                       suppelements
-                                                               ])
-                                                       );
+                                                       if (['dnsv4'].includes(ver) && Array.isArray(data[idx][ver].value)) {
+                                                               container_internet_v4.appendChild(this.renderArrayAsTable(data[idx][ver].title, data[idx][ver].value));
+                                                       } else {
+                                                               container_internet_v4.appendChild(this.renderRow(data[idx][ver].title, data[idx][ver].value, classname));
+                                                       }
                                                }
 
                                        } else {
@@ -109,13 +133,11 @@ return baseclass.extend({
                                                }
 
                                                if (visible) {
-                                                       container_internet_v6.appendChild(
-                                                               E('p', {'class': 'mt-2'}, [
-                                                                       E('span', {'class': ''}, [data[idx][ver].title + ':']),
-                                                                       E('span', {'class': classname}, [data[idx][ver].value]),
-                                                                       suppelements
-                                                               ])
-                                                       );
+                                                       if (['dnsv6'].includes(ver) && Array.isArray(data[idx][ver].value)) {
+                                                               container_internet_v6.appendChild(this.renderArrayAsTable(data[idx][ver].title, data[idx][ver].value));
+                                                       } else {
+                                                               container_internet_v6.appendChild(this.renderRow(data[idx][ver].title, data[idx][ver].value, classname));
+                                                       }
                                                }
                                        }
                                }
@@ -124,7 +146,7 @@ return baseclass.extend({
                        container_item.appendChild(container_internet_v4);
                        container_item.appendChild(container_internet_v6);
                } else {
-                       for(var idx in data) {
+                       for(let idx in data) {
                                container_item.appendChild(
                                        E('p', { 'class': 'mt-2'}, [
                                                E('span', {'class': ''}, [ data[idx].title + ':' ]),
@@ -140,22 +162,22 @@ return baseclass.extend({
                return container_wapper;
        },
 
-       renderUpdateWanData: function(data, v6) {
+       renderUpdateWanData(data, v6) {
 
-               var min_metric = 2000000000;
-               var min_metric_i = 0;
-               for (var i = 0; i < data.length; i++) {
-                       var metric = data[i].getMetric();
+               let min_metric = 2000000000;
+               let min_metric_i = 0;
+               for (let i = 0; i < data.length; i++) {
+                       const metric = data[i].getMetric();
                        if (metric < min_metric) {
                                min_metric = metric;
                                min_metric_i = i;
                        }
                 }
 
-               var ifc = data[min_metric_i];
+               const ifc = data[min_metric_i];
                if(ifc){
                        if (v6) {
-                               var uptime = ifc.getUptime();
+                               const uptime = ifc.getUptime();
                                this.params.internet.v6.uptime.value = (uptime > 0) ? '%t'.format(uptime) : '-';
                                this.params.internet.v6.ipprefixv6.value =  ifc.getIP6Prefix() || '-';
                                this.params.internet.v6.gatewayv6.value =  ifc.getGateway6Addr() || '-';
@@ -164,7 +186,7 @@ return baseclass.extend({
                                this.params.internet.v6.dnsv6.value = ifc.getDNS6Addrs() || [ '-' ];
                                this.params.internet.v6.connected.value = ifc.isUp();
                        } else {
-                               var uptime = ifc.getUptime();
+                               const uptime = ifc.getUptime();
                                this.params.internet.v4.uptime.value = (uptime > 0) ? '%t'.format(uptime) : '-';
                                this.params.internet.v4.protocol.value=  ifc.getI18n() || E('em', _('Not connected'));
                                this.params.internet.v4.gatewayv4.value =  ifc.getGatewayAddr() || '0.0.0.0';
@@ -175,7 +197,7 @@ return baseclass.extend({
                }
        },
 
-       renderInternetBox: function(data) {
+       renderInternetBox(data) {
 
                this.params.internet = {
 
@@ -272,15 +294,15 @@ return baseclass.extend({
                return this.renderHtml(this.params.internet, 'internet');
        },
 
-       renderRouterBox: function(data) {
+       renderRouterBox(data) {
 
-               var boardinfo   = data[2],
-                       systeminfo  = data[3];
+               const boardinfo   = data[2];
+               const systeminfo  = data[3];
 
-               var datestr = null;
+               let datestr = null;
 
                if (systeminfo.localtime) {
-                       var date = new Date(systeminfo.localtime * 1000);
+                       const date = new Date(systeminfo.localtime * 1000);
 
                        datestr = '%04d-%02d-%02d %02d:%02d:%02d'.format(
                                date.getUTCFullYear(),
@@ -327,7 +349,7 @@ return baseclass.extend({
                return this.renderHtml(this.params.router, 'router');
        },
 
-       render: function(data) {
+       render(data) {
                return [this.renderInternetBox(data), this.renderRouterBox(data)];
        }
 });
index 20bce46f3b6fcd9d1e7d0627ca48bfea7f1c36b8..cb2d61db23bb616f3f7f52f3e8d2682670361eef 100644 (file)
@@ -14,17 +14,17 @@ return baseclass.extend({
 
        params: {},
 
-       load: function() {
+       load() {
                return Promise.all([
                        callLuciDHCPLeases(),
                        network.getDevices()
                ]);
        },
 
-       renderHtml: function() {
+       renderHtml() {
 
-               var container_wapper = E('div', { 'class': 'router-status-lan dashboard-bg box-s1' });
-               var container_box = E('div', { 'class': 'lan-info devices-list' });
+               const container_wapper = E('div', { 'class': 'router-status-lan dashboard-bg box-s1' });
+               const container_box = E('div', { 'class': 'lan-info devices-list' });
                container_box.appendChild(E('div', { 'class': 'title'}, [
                        E('img', {
                                'src': L.resource('view/dashboard/icons/devices.svg'),
@@ -35,7 +35,7 @@ return baseclass.extend({
                        E('h3', this.title)
                ]));
 
-               var container_devices = E('table', { 'class': 'table assoclist devices-info' }, [
+               const container_devices = E('table', { 'class': 'table assoclist devices-info' }, [
                        E('tr', { 'class': 'tr dashboard-bg' }, [
                                E('th', { 'class': 'th nowrap' }, _('Hostname')),
                                E('th', { 'class': 'th' }, _('IP Address')),
@@ -43,8 +43,8 @@ return baseclass.extend({
                        ])
                ]);
 
-               for(var idx in this.params.lan.devices) {
-                       var device = this.params.lan.devices[idx];
+               for(let idx in this.params.lan.devices) {
+                       const device = this.params.lan.devices[idx];
 
                        container_devices.appendChild(E('tr', { 'class': 'tr cbi-rowstyle-1'}, [
 
@@ -74,12 +74,12 @@ return baseclass.extend({
                return container_wapper;
        },
 
-       renderUpdateData: function(data, leases) {
+       renderUpdateData(data, leases) {
 
-               for(var item in data) {
+               for(let item in data) {
                        if (/lan|br-lan/ig.test(data[item].ifname) && (typeof data[item].dev == 'object' && !data[item].dev.wireless)) {
-                               var lan_device = data[item];
-                               var ipv4addr = lan_device.dev.ipaddrs.toString().split('/');
+                               const lan_device = data[item];
+                               const ipv4addr = lan_device.dev.ipaddrs.toString().split('/');
 
                                this.params.lan.ipv4 = ipv4addr[0] || '?';
                                this.params.lan.ipv6 = ipv4addr[0] || '?';
@@ -89,8 +89,8 @@ return baseclass.extend({
                        }
                }
 
-               var devices = [];
-               leases.map(function(lease) {
+               const devices = [];
+               leases.map(lease => {
                        devices[lease.expires] = {
                                hostname: lease.hostname || '?',
                                ipv4: lease.ipaddr || '-',
@@ -100,9 +100,9 @@ return baseclass.extend({
                this.params.lan.devices = devices;
        },
 
-       renderLeases: function(data) {
+       renderLeases(data) {
 
-               var leases = Array.isArray(data[0].dhcp_leases) ? data[0].dhcp_leases : [];
+               const leases = Array.isArray(data[0].dhcp_leases) ? data[0].dhcp_leases : [];
 
                this.params.lan = {
                        ipv4: {
@@ -136,7 +136,7 @@ return baseclass.extend({
                return this.renderHtml();
        },
 
-       render: function(data) {
+       render(data) {
                if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd'))
                        return this.renderLeases(data);
 
index 7233282e33c9d4ee5624c860879a898ef8858d2e..43e7d29a1c44a5d93d31a7c171be7c985a6db285 100644 (file)
@@ -10,31 +10,31 @@ return baseclass.extend({
 
        params: [],
 
-       load: function() {
+       load() {
                return Promise.all([
                        network.getWifiDevices(),
                        network.getWifiNetworks(),
                        network.getHostHints()
-               ]).then(function(radios_networks_hints) {
-                       var tasks = [];
+               ]).then(radios_networks_hints => {
+                       const tasks = [];
 
-                       for (var i = 0; i < radios_networks_hints[1].length; i++)
-                               tasks.push(L.resolveDefault(radios_networks_hints[1][i].getAssocList(), []).then(L.bind(function(net, list) {
-                                       net.assoclist = list.sort(function(a, b) { return a.mac > b.mac });
+                       for (let i = 0; i < radios_networks_hints[1].length; i++)
+                               tasks.push(L.resolveDefault(radios_networks_hints[1][i].getAssocList(), []).then(L.bind((net, list) => {
+                                       net.assoclist = list.sort((a, b) => { return a.mac > b.mac });
                                }, this, radios_networks_hints[1][i])));
 
-                       return Promise.all(tasks).then(function() {
+                       return Promise.all(tasks).then(() => {
                                return radios_networks_hints;
                        });
                });
        },
 
-       renderHtml: function() {
+       renderHtml() {
 
-               var container_wapper = E('div', { 'class': 'router-status-wifi dashboard-bg box-s1' });
-               var container_box = E('div', { 'class': 'wifi-info devices-list' });
-               var container_radio = E('div', { 'class': 'settings-info' });
-               var container_radio_item;
+               const container_wapper = E('div', { 'class': 'router-status-wifi dashboard-bg box-s1' });
+               const container_box = E('div', { 'class': 'wifi-info devices-list' });
+               const container_radio = E('div', { 'class': 'settings-info' });
+               let container_radio_item;
 
                container_box.appendChild(E('div', { 'class': 'title'}, [
                        E('img', {
@@ -46,13 +46,13 @@ return baseclass.extend({
                        E('h3', this.title)
                ]));
 
-               for (var i =0; i < this.params.wifi.radios.length; i++) {
+               for (let i = 0; i < this.params.wifi.radios.length; i++) {
 
                        container_radio_item = E('div', { 'class': 'radio-info' })
 
-                       for(var idx in this.params.wifi.radios[i]) {
-                               var classname = idx,
-                                       radio = this.params.wifi.radios[i];
+                       for(let idx in this.params.wifi.radios[i]) {
+                               let classname = idx;
+                               const radio = this.params.wifi.radios[i];
 
                                if (!radio[idx].visible) {
                                        continue;
@@ -76,7 +76,7 @@ return baseclass.extend({
 
                container_box.appendChild(container_radio);
 
-               var container_devices = E('table', { 'class': 'table assoclist devices-info' }, [
+               const container_devices = E('table', { 'class': 'table assoclist devices-info' }, [
                        E('tr', { 'class': 'tr dashboard-bg' }, [
                                E('th', { 'class': 'th nowrap' }, _('Hostname')),
                                E('th', { 'class': 'th' }, _('SSID')),
@@ -85,17 +85,17 @@ return baseclass.extend({
                        ])
                ]);
 
-               for (var i =0; i < this.params.wifi.devices.length; i++) {
-                       var container_devices_item = E('tr', { 'class': 'tr cbi-rowstyle-1' });
+               for (let i = 0; i < this.params.wifi.devices.length; i++) {
+                       const container_devices_item = E('tr', { 'class': 'tr cbi-rowstyle-1' });
 
-                       for(var idx in this.params.wifi.devices[i]) {
-                               var device = this.params.wifi.devices[i];
+                       for(let idx in this.params.wifi.devices[i]) {
+                               const device = this.params.wifi.devices[i];
 
                                if (!device[idx].visible) {
                                        continue;
                                }
 
-                               var container_content;
+                               let container_content;
 
                                if ('progress' == idx) {
                                        container_content = E('div', { 'class' : 'td device-info' }, [
@@ -131,19 +131,19 @@ return baseclass.extend({
                return container_wapper;
        },
 
-       renderUpdateData: function(radios, networks, hosthints) {
+       renderUpdateData(radios, networks, hosthints) {
 
-               for (var i = 0; i < radios.sort(function(a, b) { a.getName() > b.getName() }).length; i++) {
-                       var network_items = networks.filter(function(net) { return net.getWifiDeviceName() == radios[i].getName() });
+               for (let i = 0; i < radios.sort((a, b) => { a.getName() > b.getName() }).length; i++) {
+                       const network_items = networks.filter(net => { return net.getWifiDeviceName() == radios[i].getName() });
 
-                       for (var j = 0; j < network_items.length; j++) {
-                                var net = network_items[j],
-                                        is_assoc = (net.getBSSID() != '00:00:00:00:00:00' && net.getChannel() && !net.isDisabled()),
-                                        chan = net.getChannel(),
-                                        freq = net.getFrequency(),
-                                        rate = net.getBitRate();
+                       for (let j = 0; j < network_items.length; j++) {
+                               const net = network_items[j];
+                               const is_assoc = (net.getBSSID() != '00:00:00:00:00:00' && net.getChannel() && !net.isDisabled());
+                               const chan = net.getChannel();
+                               const freq = net.getFrequency();
+                               const rate = net.getBitRate();
 
-                                this.params.wifi.radios.push(
+                               this.params.wifi.radios.push(
                                        {
                                                ssid : {
                                                        title: _('SSID'),
@@ -191,16 +191,16 @@ return baseclass.extend({
                        }
                }
 
-               for (var i = 0; i < networks.length; i++) {
-                       for (var k = 0; k < networks[i].assoclist.length; k++) {
-                               var bss = networks[i].assoclist[k],
-                                       name = hosthints.getHostnameByMACAddr(bss.mac);
+               for (let i = 0; i < networks.length; i++) {
+                       for (let k = 0; k < networks[i].assoclist.length; k++) {
+                               const bss = networks[i].assoclist[k];
+                               const name = hosthints.getHostnameByMACAddr(bss.mac);
 
-                               var progress_style;
-                               var defaultNF = -90; // default noise floor for devices that do not report it
-                               var defaultCeil = -30;
-                               // var q = Math.min((bss.signal + 110) / 70 * 100, 100);
-                               var q = 100 * ((bss.signal - (bss.noise ? bss.noise: defaultNF) ) / (defaultCeil - (bss.noise ? bss.noise : defaultNF)));
+                               let progress_style;
+                               const defaultNF = -90; // default noise floor for devices that do not report it
+                               const defaultCeil = -30;
+                               // const q = Math.min((bss.signal + 110) / 70 * 100, 100);
+                               const q = 100 * ((bss.signal - (bss.noise ? bss.noise: defaultNF) ) / (defaultCeil - (bss.noise ? bss.noise : defaultNF)));
 
                                if (q == 0 || q < 25)
                                        progress_style = 'bg-danger';
@@ -249,7 +249,7 @@ return baseclass.extend({
                }
        },
 
-       render: function(data) {
+       render(data) {
 
                this.params.wifi = {
                        radios: [],
index c3e3b702716df839dcc686679f187a1a757be06c..6e9d8599b2bd06a46a13c47fe835d8f84aea05c0 100644 (file)
@@ -12,11 +12,12 @@ document.querySelector('head').appendChild(E('link', {
 }));
 
 function invokeIncludesLoad(includes) {
-       var tasks = [], has_load = false;
+       const tasks = [];
+       let has_load = false;
 
-       for (var i = 0; i < includes.length; i++) {
+       for (let i = 0; i < includes.length; i++) {
                if (typeof(includes[i].load) == 'function') {
-                       tasks.push(includes[i].load().catch(L.bind(function() {
+                       tasks.push(includes[i].load().catch(L.bind(() => {
                                this.failed = true;
                        }, includes[i])));
 
@@ -31,12 +32,12 @@ function invokeIncludesLoad(includes) {
 }
 
 function startPolling(includes, containers) {
-       var step = function() {
-               return network.flushCache().then(function() {
+       const step = () => {
+               return network.flushCache().then(() => {
                        return invokeIncludesLoad(includes);
-               }).then(function(results) {
-                       for (var i = 0; i < includes.length; i++) {
-                               var content = null;
+               }).then(results => {
+                       for (let i = 0; i < includes.length; i++) {
+                               let content = null;
 
                                if (includes[i].failed)
                                        continue;
@@ -59,7 +60,7 @@ function startPolling(includes, containers) {
                                }
                        }
 
-                       var ssi = document.querySelector('div.includes');
+                       const ssi = document.querySelector('div.includes');
                        if (ssi) {
                                ssi.style.display = '';
                                ssi.classList.add('fade-in');
@@ -67,30 +68,31 @@ function startPolling(includes, containers) {
                });
        };
 
-       return step().then(function() {
+       return step().then(() => {
                poll.add(step);
        });
 }
 
 return view.extend({
-       load: function() {
-               return L.resolveDefault(fs.list('/www' + L.resource('view/dashboard/include')), []).then(function(entries) {
-                       return Promise.all(entries.filter(function(e) {
+       load() {
+               return L.resolveDefault(fs.list('/www' + L.resource('view/dashboard/include')), []).then(entries => {
+                       return Promise.all(entries.filter(e => {
                                return (e.type == 'file' && e.name.match(/\.js$/));
-                       }).map(function(e) {
+                       }).map(e => {
                                return 'view.dashboard.include.' + e.name.replace(/\.js$/, '');
-                       }).sort().map(function(n) {
+                       }).sort().map(n => {
                                return L.require(n);
                        }));
                });
        },
 
-       render: function(includes) {
-               var rv = E([]), containers = [];
+       render(includes) {
+               const rv = E([]);
+               const containers = [];
 
-               for (var i = 0; i < includes.length - 1; i++) {
+               for (let i = 0; i < includes.length - 1; i++) {
 
-                       var container = E('div', { 'class': 'section-content' });
+                       const container = E('div', { 'class': 'section-content' });
 
                        rv.appendChild(E('div', { 'class': 'cbi-section-' + i, 'style': 'display:none' }, [
                                container
@@ -99,7 +101,7 @@ return view.extend({
                        containers.push(container);
                }
 
-               return startPolling(includes, containers).then(function() {
+               return startPolling(includes, containers).then(() => {
                        return rv;
                });
        },